wait、notify、sleep、interrupt对比分析 您所在的位置:网站首页 java wait与sleep的区别 wait、notify、sleep、interrupt对比分析

wait、notify、sleep、interrupt对比分析

2023-09-09 21:45| 来源: 网络整理| 查看: 265

方法简述 Thread类 sleep:暂停当前正在执行的线程;(类方法)yield:放弃当前CPU资源,让其他任务去占用CPU执行时间,放弃的时间不确定,有可能刚刚放弃,马上又获得CPU时间片。(类方法)join:等待该线程终止;interrupt:仅仅是在当前线程上做一个停止的标记,并不会真正的停止线程,与interrupted()静态方法或isInterrupted()实例方法配合使用,达到中断线程的目的。当线程调用wait(),sleep(),join()或I/O操作时,将收到InterruptedException或 ClosedByInterruptException; //静态方法获取当前线程的中断情况,并且清除中断状态 public static boolean interrupted() { return currentThread().isInterrupted(true); } //实例方法,返回当前实例线程的中断情况,并且不清楚中断状态 public boolean isInterrupted() { return isInterrupted(false); }

 

Object类 wait:暂停当前正在执行的线程,直到调用notify()或notifyAll()方法或超时,退出等待状态;notify:唤醒在该对象上等待的一个线程;notifyAll:唤醒在该对象上等待的所有线程; 详细分析 sleep VS wait

sleep()和wait()方法都是暂停当前正在执行的线程,出让CPU资源。

方法所属类方法类型锁解除方法场景用途sleepThread静态方法不释放锁timeout,interrupt无限制线程内的控制waitObject非静态方法释放锁timeout,notify,interrupt同步语句块线程间的通信 public static void sleep(long millis) throws InterruptedException public static void sleep(long millis, int nanos) throws InterruptedException public final void wait() throws InterruptedException public final void wait(long timeout) throws InterruptedException public final void wait(long timeout, int nanos) throws InterruptedException interrupt

interrupt()方法的工作仅仅是改变中断状态,并不是直接中断正在运行的线程。中断的真正原理是当线程被Object.wait(),Thread.join()或sleep()方法阻塞时,调用interrupt()方法后改变中断状态,而wait/join/sleep这些方法内部会不断地检查线程的中断状态值,当发现中断状态值改变时则抛出InterruptedException异常,从而结束阻塞;对于没有阻塞的线程,调用interrupt()方法是没有任何作用。

常用的一个例子如下:

package concurrent; public class InterruptedTest implements Runnable{ @Override public void run() { try{ for(int i = 0; i < Integer.MAX_VALUE; i++){ if(Thread.interrupted()){ System.out.println("已经中断,运行次数为:" + i); throw new InterruptedException(); } } } catch(InterruptedException e){ System.out.println("线程catch 方法"); } } } package test; import concurrent.InterruptedTest; class Test { public static void main(String[] args) { try { InterruptedTest test = new InterruptedTest(); Thread thread = new Thread(test); thread.start(); try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } thread.interrupt(); } catch (Exception e) { System.out.println("main catch方法"); } } }

最终的打印效果大概如下图所示:

yield

它仅仅释放线程所占有的CPU资源,从而让其他线程有机会运行,但是并不能保证某个特定的线程能够获得CPU资源,也有可能在释放CPU资源后又重新获得CPU资源。所以,依赖于yield方法是不可靠的,它在不同的系统和jvm实现上的表现会略有不同。

public class yieldTest { public static void main(String[] args){ Thread yieldTest = new Thread( () -> { long startTime = System.currentTimeMillis(); for (int i = 1; i < 9999999; i++){ Thread.yield(); } System.out.println("运行时长为:" + (System.currentTimeMillis() - startTime)); } ); yieldTest.start(); } }

以上面这段代码为例,每次执行的时长是不确定的

但是如果注释掉Thread.yield()之后,其执行时长基本是确定的

public class yieldTest { public static void main(String[] args){ Thread yieldTest = new Thread( () -> { long startTime = System.currentTimeMillis(); for (int i = 1; i < 9999999; i++){ //Thread.yield(); } System.out.println("运行时长为:" + (System.currentTimeMillis() - startTime)); } ); yieldTest.start(); } }

运行了5次的执行时长都相同

  Wait vs Sleep vs Yield in Java Java中wait和sleep的区别

wait和sleep的主要区别是调用wait方法时,线程在等待的时候会释放掉它所获得的monitor,但是调用Thread.sleep()方法时,线程在等待的时候仍然会持有monitor或者锁。另外,Java中的wait方法应在同步代码块中调用,但是sleep方法不需要。 另一个区别是Thread.sleep()方法是一个静态方法,作用在当前线程上;但是wait方法是一个实例方法,并且只能在其他线程调用本实例的notify()方法时被唤醒。另外,使用sleep方法时,被暂停的线程在被唤醒之后会立即进入就绪态(Runnable state),但是使用wait方法的时候,被暂停的线程会首先获得锁(译者注:阻塞态),然后再进入就绪态。所以,根据你的需求,如果你需要暂定你的线程一段特定的时间就使用sleep()方法,如果你想要实现线程间通信就使用wait()方法。 下面列出Java中wait和sleep方法的区别:

wait只能在同步(synchronize)环境中被调用,而sleep不需要。详见Why to wait and notify needs to call from synchronized method进入wait状态的线程能够被notify和notifyAll线程唤醒,但是进入sleeping状态的线程不能被notify方法唤醒。wait通常有条件地执行,线程会一直处于wait状态,直到某个条件变为真。但是sleep仅仅让你的线程进入睡眠状态。wait方法在进入wait状态的时候会释放对象的锁,但是sleep方法不会。wait方法是针对一个被同步代码块加锁的对象,而sleep是针对一个线程。更详细的讲解可以参考《Java核心技术卷1》,里面介绍了如何使用wait和notify方法。 yield和sleep的区别

yield和sleep的主要是,yield让出cpu执行权,如果没有正在等待的线程,或者所有正在等待的线程的优先级都比较低,那么该线程会继续运行。执行了yield方法的线程什么时候会继续运行由线程调度器来决定,不同的厂商可能有不同的行为。yield方法不保证当前的线程会暂停或者停止,但是可以保证当前线程在调用yield方法时会让出cpu执行权。 在Java中Sleep方法有两个, 一个只有一个毫秒参数,另一个有毫秒和纳秒两个参数。

Java中sleep方法的几个注意点:

Thread.sleep()方法用来暂停线程的执行,将CPU放给线程调度器。Thread.sleep()方法是一个静态方法,它暂停的是当前执行的线程。Java有两种sleep方法,一个只有一个毫秒参数,另一个有毫秒和纳秒两个参数。与wait方法不同,sleep方法不会释放锁如果其他的线程中断了一个休眠的线程,sleep方法会抛出Interrupted Exception。休眠的线程在唤醒之后不保证能获取到CPU,它会先进入就绪态,与其他线程竞争CPU。有一个易错的地方,当调用t.sleep()的时候,会暂停线程t。这是不对的,因为Thread.sleep是一个静态方法,它会使当前线程而不是线程t进入休眠状态。

这就是java中的sleep方法。我们已经看到了java中sleep、wait以及yield方法的区别。总之,记住sleep和yield作用于当前线程。

参考:

https://www.cnblogs.com/andlp/p/5886151.html

https://www.jianshu.com/p/25e959037eed

 



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有